package com.paginasenlanube.dao;



import java.util.Iterator;
import java.util.List;
import java.util.Map;


import org.hibernate.Criteria;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;

@Repository("hibernateDao")
public class HibernateDaoImpl implements GenericDao {
	
	@Autowired
    private SessionFactory sessionFactory;
    
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
		
    public Session getSession() {
		return this.getSessionFactory().getCurrentSession();
	}
    
    @Override
	public void add(Object obj) {
		getSession().save(obj);   
    }
	

	@Override
	public void delete(Object obj) {
		getSession().delete(obj);
		
	}
    
	@Override
    public void update(Object obj) {  	
    	getSession().update(obj);    
    }

    
    /**
     * Returns an ordered List of objects filter by params. 
     * If Order is null then no order its apply.
     * @param  entityClass  the class of the entities list.
     * @param  params  a Map with the params for an equal filter
     * @param  Order  hibernate.criterion.Order for ordering the resulting List
     * @return      a list with objects of type entityClass   
     */
	@Override
	public <T> List<T> getObjectsByEqCriteria(Class<T> entityClass, Map<String, ?> params, Order order) {
		
		Criteria cr = getSession().createCriteria(entityClass);
		Iterator<?> it = params.entrySet().iterator();
		 while (it.hasNext()) {
		        @SuppressWarnings("unchecked")
				Map.Entry<String, Object> pairs = (Map.Entry<String, Object>)it.next();
		        cr.add(Restrictions.eq(pairs.getKey(), pairs.getValue()));
		        it.remove(); // avoids a ConcurrentModificationException
		    }
		        if(order != null)cr.addOrder(order);
				@SuppressWarnings("unchecked")
				List<T> results = (List<T>) cr.list();		
		return results;
	}


	@Override
	public <T> T getObjectById(Class<T> entityClass, long id) {
		@SuppressWarnings("unchecked")
		T result = (T) getSession().load(entityClass, id);
		return result;
	}
	
	
	@Override
	public <T> Integer getObjectValueByMaxCriteria(Class<T> entityClass, String field, Map<String, ?> params) {
		Criteria cr = getSession().createCriteria(entityClass);
	    cr.setProjection(Projections.max(field));
	    if(params != null){
	    Iterator<?> it = params.entrySet().iterator();
		 while (it.hasNext()) {
		        @SuppressWarnings("unchecked")
				Map.Entry<String, Object> pairs = (Map.Entry<String, Object>)it.next();
		        cr.add(Restrictions.eq(pairs.getKey(), pairs.getValue()));
		        it.remove(); // avoids a ConcurrentModificationException
	    }
	    }
	    Integer maxPosition = (Integer) cr.uniqueResult();	
		return maxPosition;
	}

	@Override
	public <T> boolean deleteObjectsByEqCriteria(Class<T> entityClass,Map<String, ?> params) {
		List<T> objs = getObjectsByEqCriteria(entityClass,params,null);
		for(T obj : objs){
			getSession().delete(obj);
		}
		return true;
	}




	
    
    


	



}
